//! @Author: DengLibin 榆霖
//! @Date:  2022-07-07 13:41:15
//! @Description:

use std::{collections::HashMap};

use common::date;
use mysql::{params, prelude::Queryable, TxOpts};

use crate::{
    entity::article::{Article},
    pojo::PageInfo,
};

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-07 13:43:54
/// @Description: 添加
pub fn insert(a: &Article, pool: &mysql::Pool) -> Result<bool, Box<dyn std::error::Error>> {
    let mut conn = pool.get_conn()?;
    let mut tx = conn.start_transaction(TxOpts::default())?;

    tx.exec_drop(
        "INSERT INTO Article (id, parent_id, create_time, title, content) 
        VALUES (?,?,?,?,?)",
        (
            a.id,
            a.parent_id,
            date::get_chrono_local_now_time_str(),
            &a.title,
            &a.content,
        ),
    )?;
    tx.commit()?;
    return Ok(true);
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-07 13:51:42
/// @Description: 批量天啊及
pub fn insert_batch(
    articles: &Vec<Article>,
    pool: &mysql::Pool,
) -> Result<u64, Box<dyn std::error::Error>> {
    let mut conn = pool.get_conn()?;
    conn.exec_batch(
        r"INSERT INTO Article (id, parent_id, create_time, title, content)
          VALUES (:id, :create_time, :title, :content)",
        articles.iter().map(|a| {
            params! {
                "id" => a.id,
                "parent_id" => a.parent_id,
                "create_time" => date::get_chrono_local_now_time_str(),
                "title" => &a.title,
                "content" => &a.content,
            }
        }),
    )?;
    let affect_row = conn.affected_rows();
    drop(conn);
    return Ok(affect_row);
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-07 13:51:21
/// @Description: 所有
pub fn get_all(pool: &mysql::Pool) -> Result<Vec<Article>, Box<dyn std::error::Error>> {
    let mut conn = pool.get_conn()?;
    let articles = conn.query_map(
        "SELECT id, parent_id, create_time, title, left(content, 200) as content FROM article ORDER BY ID",
        |(id, parent_id, create_time, title, content)| Article {
            id,
            parent_id,
            create_time,
            title,
            content,
        },
    )?;
    return Ok(articles);
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-07 13:51:13
/// @Description: 分页
pub fn get_page(
    page: i32,
    size: i32,
    pool: &mysql::Pool,
) -> Result<PageInfo<Article>, Box<dyn std::error::Error>> {
    let mut conn = pool.get_conn()?;
    let sql_list = "SELECT id, create_time, title, left(content, 200) as content FROM article";

    //查询总数
    let sql_total = format!("SELECT COUNT(1) FROM ({}) t", sql_list);
    //分页
    let sql_page = format!("{} LIMIT {} OFFSET  {}", sql_list, size, (page - 1) * size);

    //列表
    let articles = conn.query_map(sql_page, |(id, parent_id,create_time, title, content)| Article {
        id,
        parent_id,
        create_time,
        title,
        content,
    })?;
    //总数
    let r = conn.query_first::<i32, &str>(sql_total.as_str());
    let total = match r {
        Ok(o) => match o {
            Some(t) => t,
            None => 0,
        },
        Err(e) => {
            error!("get_page--------------------::{}", e);
            0
        }
    };

    return Ok(PageInfo {
        page: page,
        size: size,
        total,
        list: articles,
    });
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-05 10:06:56
/// @Description: 删除
pub fn delete(id: i64, pool: &mysql::Pool) -> Result<bool, Box<dyn std::error::Error>> {
    let delete_sql = "DELETE FROM article where id = ?";

    let mut conn = pool.get_conn()?;
    let mut tx = conn.start_transaction(TxOpts::default())?;
    tx.exec_drop(delete_sql, (id,))?;
    tx.commit()?;
    return Ok(true);
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-05 10:17:46
/// @Description: 更新
pub fn update(
    map: HashMap<&str, &str>,
    id: i64,
    pool: &mysql::Pool,
) -> Result<bool, Box<dyn std::error::Error>> {
    let mut update_sql = String::from("UPDATE article SET ");
    let size = map.len();
    let mut index = 0;
    //保存参数
    let mut values: Vec<&str> = vec![];
    //遍历
    for (k, v) in map {
        update_sql.push_str(k);
        update_sql.push_str("=");
        update_sql.push_str("?");
        //参数
        values.insert(index, v);
        index += 1;
        if index < size {
            update_sql.push(',');
        }
    }
    update_sql.push_str(" WHERE ID = ?");
    let str_id = format!("{}", id);
    //id
    values.insert(index, &str_id);

    let mut conn = pool.get_conn()?;
    let mut tx = conn.start_transaction(TxOpts::default())?;
    //执行更新
    tx.exec_drop(update_sql.as_str(), values)?;
    tx.commit()?;
    return Ok(true);
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-18 15:39:36
/// @Description: 根据id查询
pub fn get_by_id(id: i64, pool: &mysql::Pool) -> Option<Article> {

    let mut conn = pool.get_conn().unwrap();
    let sql = format!("SELECT id, parent_id, create_time, title, content FROM article where id={}", id);
      //列表
    let mut articles = conn.query_map(sql, |(id, parent_id,create_time, title, content)| Article {
        id,
        parent_id,
        create_time,
        title,
        content,
    }).unwrap();
    let a = articles.pop();
    
    return a;

 }